//	Project: Handle Template Library
//	File:    CSync.h
//	Author:  Paul Bludov
//	Date:    2002-11-04
//
//	Description:
//		C++ wrapper for Win32 event, semaphore, mutex, timer
//
//	Update History:
//		NONE
//		
/////////////////////////////////////////////////////////////////////////////

#ifndef __HTLSYNC_H__
#define __HTLSYNC_H__

#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000

#include "htlhandle.h"

/////////////////////////////////////////////////////////////////////////////
// Classes in this file
//
// CEventT<t_bManaged>
// CMutexT<t_bManaged>
// CSemaphoreT<t_bManaged>
// CWaitableTimerT<t_bManaged>
// CMemoryResourceNotificationT<t_bManaged>
//

namespace HTL
{

/////////////////////////////////////////////////////////////////////////////
// Event

template<bool t_bManaged>
class CEventT
	: public CHandleT<t_bManaged>
{
	typedef CHandleT<t_bManaged> Base;
public:
	CEventT()
	{ }
	CEventT
		( const CEventT<true>& rEvent
		)
		: Base(rEvent)
	{ }
	CEventT
		( const CEventT<false>& rEvent
		)
		: Base(rEvent)
	{ }
	explicit CEventT
		( HANDLE hEvent
		)
		: Base(hEvent)
	{ }

	CEventT
		( BOOL bManualReset
		, BOOL bInitialState
		)
	{
		Create(bManualReset, bInitialState);
		_ASSERTE(IsValid());
	}

	CEventT
		( BOOL bManualReset
		, BOOL bInitialState
		, LPCSTR lpName
		, LPSECURITY_ATTRIBUTES lpEventAttributes = NULL
		)
	{
		Create(bManualReset, bInitialState, lpName, lpEventAttributes);
		_ASSERTE(IsValid());
	}

	CEventT
		( BOOL bManualReset
		, BOOL bInitialState
		, LPCWSTR lpName
		, LPSECURITY_ATTRIBUTES lpEventAttributes = NULL
		)
	{
		Create(bManualReset, bInitialState, lpName, lpEventAttributes);
		_ASSERTE(IsValid());
	}

	CEventT
		( LPCSTR lpName
		, DWORD nDesiredAccess
		, BOOL bInheritHandle = FALSE
		)
	{
		Open(lpName, nDesiredAccess, bInheritHandle);
		_ASSERTE(IsValid());
	}

	CEventT
		( LPCWSTR lpName
		, DWORD nDesiredAccess
		, BOOL bInheritHandle = FALSE
		)
	{
		Open(lpName, nDesiredAccess, bInheritHandle);
		_ASSERTE(IsValid());
	}

	CEventT<t_bManaged>& operator=(HANDLE h)
	{
		Base::operator=(h);
		return *this;
	}

	CEventT<t_bManaged>& operator=(const CEventT<true>& other)
	{
		Base::operator=(other);
		return *this;
	}

	CEventT<t_bManaged>& operator=(const CEventT<false>& other)
	{
		Base::operator=(other);
		return *this;
	}

	HANDLE Create
		( BOOL bManualReset
		, BOOL bInitialState
		)
	{
		_ASSERTE(!IsValid());

		m_h = ::CreateEvent(NULL, bManualReset, bInitialState, NULL);
		return m_h;
	}

	HANDLE Create
		( BOOL bManualReset
		, BOOL bInitialState
		, LPCSTR lpName
		, LPSECURITY_ATTRIBUTES lpEventAttributes = NULL
		)
	{
		_ASSERTE(!IsValid());

		m_h = ::CreateEventA(lpEventAttributes, bManualReset, bInitialState
			, lpName);
		return m_h;
	}

	HANDLE Create
		( BOOL bManualReset
		, BOOL bInitialState
		, LPCWSTR lpName
		, LPSECURITY_ATTRIBUTES lpEventAttributes = NULL
		)
	{
		_ASSERTE(!IsValid());

		m_h = ::CreateEventW(lpEventAttributes, bManualReset, bInitialState
			, lpName);
		return m_h;
	}

	HANDLE Open
		( LPCSTR lpName
		, DWORD nDesiredAccess = EVENT_ALL_ACCESS
		, BOOL bInheritHandle = FALSE
		)
	{
		_ASSERTE(!IsValid());

		m_h = ::OpenEventA(nDesiredAccess, bInheritHandle, lpName);
		return m_h;
	}

	HANDLE Open
		( LPCWSTR lpName
		, DWORD nDesiredAccess = EVENT_ALL_ACCESS
		, BOOL bInheritHandle = FALSE
		)
	{
		_ASSERTE(!IsValid());

		m_h = ::OpenEventW(nDesiredAccess, bInheritHandle, lpName);
		return m_h;
	}

	BOOL Pulse()
	{
		_ASSERTE(IsValid());

		return ::PulseEvent(m_h);
	}

	BOOL Set()
	{
		_ASSERTE(IsValid());

		return ::SetEvent(m_h);
	}

	BOOL Reset()
	{
		_ASSERTE(IsValid());

		return ::ResetEvent(m_h);
	}

#if(_WIN32_WINNT >= 0x0400)

	DWORD SignalMeAndWaitOther
		( HANDLE hObjectToWait
		, DWORD nMilliseconds = INFINITE
		, BOOL bAlertable = FALSE
		)
	{
		_ASSERTE(IsValidHandle(hObjectToWait));
		_ASSERTE(IsValid());

		return ::SignalObjectAndWait(m_h, hObjectToWait, nMilliseconds
			, bAlertable);
	}

#endif // (_WIN32_WINNT >= 0x0400)
};

typedef CEventT<true> CEvent;
typedef CEventT<false> CEventHandle;

//@//////////////////////////////////////////////////////////////////////////
// Mutex

template<bool t_bManaged>
class CMutexT
	: public CHandleT<t_bManaged>
{
	typedef CHandleT<t_bManaged> Base;
public:
	CMutexT()
	{ }
	CMutexT
		( const CMutexT<true>& rMutex
		)
		: Base(rMutex)
	{ }
	CMutexT
		( const CMutexT<false>& rMutex
		)
		: Base(rMutex)
	{ }
	explicit CMutexT
		( HANDLE hMutex
		)
		: Base(hMutex)
	{ }

	explicit CMutexT
		( BOOL bInitialOwner 
		)
	{
		Create(bInitialOwner);
		_ASSERTE(IsValid());
	}

	CMutexT
		( BOOL bInitialOwner 
		, LPCSTR lpName
		, LPSECURITY_ATTRIBUTES lpMutexAttributes = NULL
		)
	{
		Create(bInitialOwner, lpName, lpMutexAttributes);
		_ASSERTE(IsValid());
	}

	explicit CMutexT
		( BOOL bInitialOwner 
		, LPCWSTR lpName
		, LPSECURITY_ATTRIBUTES lpMutexAttributes = NULL
		)
	{
		Create(bInitialOwner, lpName, lpMutexAttributes);
		_ASSERTE(IsValid());
	}

	CMutexT
		( LPCSTR lpName
		, DWORD nDesiredAccess
		, BOOL bInheritHandle = FALSE
		)
	{
		Open(lpName, nDesiredAccess, bInheritHandle);
		_ASSERTE(IsValid());
	}

	CMutexT
		( LPCWSTR lpName
		, DWORD nDesiredAccess
		, BOOL bInheritHandle = FALSE
		)
	{
		Open(lpName, nDesiredAccess, bInheritHandle);
		_ASSERTE(IsValid());
	}

	CMutexT<t_bManaged>& operator=(HANDLE h)
	{
		Base::operator=(h);
		return *this;
	}

	CMutexT<t_bManaged>& operator=(const CMutexT<true>& other)
	{
		Base::operator=(other);
		return *this;
	}

	CMutexT<t_bManaged>& operator=(const CMutexT<false>& other)
	{
		Base::operator=(other);
		return *this;
	}

	HANDLE Create
		( BOOL bInitialOwner 
		)
	{
		_ASSERTE(!IsValid());

		m_h = ::CreateMutex(NULL, bInitialOwner, NULL);
		return m_h;
	}

	HANDLE Create
		( BOOL bInitialOwner 
		, LPCSTR lpName
		, LPSECURITY_ATTRIBUTES lpMutexAttributes = NULL
		)
	{
		_ASSERTE(!IsValid());

		m_h = ::CreateMutexA(lpMutexAttributes, bInitialOwner, lpName);
		return m_h;
	}

	HANDLE Create
		( BOOL bInitialOwner 
		, LPCWSTR lpName
		, LPSECURITY_ATTRIBUTES lpMutexAttributes = NULL
		)
	{
		_ASSERTE(!IsValid());

		m_h = ::CreateMutexW(lpMutexAttributes, bInitialOwner, lpName);
		return m_h;
	}

	HANDLE Open
		( LPCSTR lpName
		, DWORD nDesiredAccess = MUTEX_ALL_ACCESS
		, BOOL bInheritHandle = FALSE
		)
	{
		_ASSERTE(!IsValid());

		m_h = ::OpenMutexA(nDesiredAccess, bInheritHandle, lpName);
		return m_h;
	}

	HANDLE Open
		( LPCWSTR lpName
		, DWORD nDesiredAccess = MUTEX_ALL_ACCESS
		, BOOL bInheritHandle = FALSE
		)
	{
		_ASSERTE(!IsValid());

		m_h = ::OpenMutexW(nDesiredAccess, bInheritHandle, lpName);
		return m_h;
	}

	BOOL Release()
	{
		_ASSERTE(IsValid());

		return ::ReleaseMutex(m_h);
	}

#if(_WIN32_WINNT >= 0x0400)

	DWORD SignalMeAndWaitOther
		( HANDLE hObjectToWait
		, DWORD nMilliseconds = INFINITE
		, BOOL bAlertable = FALSE
		)
	{
		_ASSERTE(IsValidHandle(hObjectToWait));
		_ASSERTE(IsValid());

		return ::SignalObjectAndWait(m_h, hObjectToWait, nMilliseconds
			, bAlertable);
	}

#endif // (_WIN32_WINNT >= 0x0400)
};

typedef CMutexT<true> CMutex;
typedef CMutexT<false> CMutexHandle;

//@//////////////////////////////////////////////////////////////////////////
// Semaphore

template<bool t_bManaged>
class CSemaphoreT
	: public CHandleT<t_bManaged>
{
	typedef CHandleT<t_bManaged> Base;
public:
	CSemaphoreT()
	{ }
	CSemaphoreT
		( const CSemaphoreT<true>& rSemaphore
		)
		: Base(rSemaphore)
	{ }
	CSemaphoreT
		( const CSemaphoreT<false>& rSemaphore
		)
		: Base(rSemaphore)
	{ }
	explicit CSemaphoreT
		( HANDLE hSemaphore
		)
		: Base(hSemaphore)
	{ }

	CSemaphoreT
		( LONG lInitialCount
		, LONG lMaximumCount
		)
	{
		Create(lInitialCount, lMaximumCount);
		_ASSERTE(IsValid());
	}

	CSemaphoreT
		( LONG lInitialCount
		, LONG lMaximumCount
		, LPCSTR lpName
		, LPSECURITY_ATTRIBUTES lpSemaphoreAttributes = NULL
		)
	{
		Create(lInitialCount, lMaximumCount, lpName, lpSemaphoreAttributes);
		_ASSERTE(IsValid());
	}

	CSemaphoreT
		( LONG lInitialCount
		, LONG lMaximumCount
		, LPCWSTR lpName
		, LPSECURITY_ATTRIBUTES lpSemaphoreAttributes = NULL
		)
	{
		Create(lInitialCount, lMaximumCount, lpName, lpSemaphoreAttributes);
		_ASSERTE(IsValid());
	}

	CSemaphoreT
		( LPCSTR lpName
		, DWORD nDesiredAccess
		, BOOL bInheritHandle = FALSE
		)
	{
		Open(lpName, nDesiredAccess, bInheritHandle);
		_ASSERTE(IsValid());
	}

	CSemaphoreT
		( LPCWSTR lpName
		, DWORD nDesiredAccess
		, BOOL bInheritHandle = FALSE
		)
	{
		Open(lpName, nDesiredAccess, bInheritHandle);
		_ASSERTE(IsValid());
	}

	CSemaphoreT<t_bManaged>& operator=(HANDLE h)
	{
		Base::operator=(h);
		return *this;
	}

	CSemaphoreT<t_bManaged>& operator=(const CSemaphoreT<true>& other)
	{
		Base::operator=(other);
		return *this;
	}

	CSemaphoreT<t_bManaged>& operator=(const CSemaphoreT<false>& other)
	{
		Base::operator=(other);
		return *this;
	}

	HANDLE Create
		( LONG lInitialCount
		, LONG lMaximumCount
		)
	{
		_ASSERTE(!IsValid());

		m_h = ::CreateSemaphore(NULL, lInitialCount, lMaximumCount, NULL);
		return m_h;
	}

	HANDLE Create
		( LONG lInitialCount
		, LONG lMaximumCount
		, LPCSTR lpName
		, LPSECURITY_ATTRIBUTES lpSemaphoreAttributes = NULL
		)
	{
		_ASSERTE(!IsValid());

		m_h = ::CreateSemaphoreA(lpSemaphoreAttributes, lInitialCount
			, lMaximumCount, lpName);
		return m_h;
	}

	HANDLE Create
		( LONG lInitialCount
		, LONG lMaximumCount
		, LPCWSTR lpName
		, LPSECURITY_ATTRIBUTES lpSemaphoreAttributes = NULL
		)
	{
		_ASSERTE(!IsValid());

		m_h = ::CreateSemaphoreW(lpSemaphoreAttributes, lInitialCount
			, lMaximumCount, lpName);
		return m_h;
	}

	HANDLE Open
		( LPCSTR lpName
		, DWORD nDesiredAccess = SEMAPHORE_ALL_ACCESS
		, BOOL bInheritHandle = FALSE
		)
	{
		_ASSERTE(!IsValid());

		m_h = ::OpenSemaphoreA(nDesiredAccess, bInheritHandle, lpName);
		return	m_h;
	}

	HANDLE Open
		( LPCWSTR lpName
		, DWORD nDesiredAccess = SEMAPHORE_ALL_ACCESS
		, BOOL bInheritHandle = FALSE
		)
	{
		_ASSERTE(!IsValid());

		m_h = ::OpenSemaphoreW(nDesiredAccess, bInheritHandle, lpName);
		return	m_h;
	}

	BOOL Release
		( LONG lReleaseCount = 1
		, LPLONG lpPreviousCount = NULL
		)
	{
		_ASSERTE(IsValid());

		return ::ReleaseSemaphore(m_h, lReleaseCount, lpPreviousCount);
	}

#if(_WIN32_WINNT >= 0x0400)

	DWORD SignalMeAndWaitOther
		( HANDLE hObjectToWait
		, DWORD nMilliseconds = INFINITE
		, BOOL bAlertable = FALSE
		)
	{
		_ASSERTE(IsValidHandle(hObjectToWait));
		_ASSERTE(IsValid());

		return ::SignalObjectAndWait(m_h, hObjectToWait, nMilliseconds
			, bAlertable);
	}

#endif // (_WIN32_WINNT >= 0x0400)
};

typedef CSemaphoreT<true> CSemaphore;
typedef CSemaphoreT<false> CSemaphoreHandle;

/////////////////////////////////////////////////////////////////////////////
// WaitableTimer

#if (_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)

template<bool t_bManaged>
class CWaitableTimerT
	: public CHandleT<t_bManaged>
{
	typedef CHandleT<t_bManaged> Base;
public:
	CWaitableTimerT()
	{ }
	CWaitableTimerT
		( const CWaitableTimerT<true>& rTimer
		)
		: Base(rTimer)
	{ }
	CWaitableTimerT
		( const CWaitableTimerT<false>& rTimer
		)
		: Base(rTimer)
	{ }
	explicit CWaitableTimerT
		( HANDLE hTimer
		)
		: Base(hTimer)
	{ }

	explicit CWaitableTimerT
		( BOOL bManualReset
		)
	{
		Create(bManualReset);
		_ASSERTE(IsValid());
	}

	CWaitableTimerT
		( BOOL bManualReset
		, LPCSTR lpName
		, LPSECURITY_ATTRIBUTES lpTimerAttributes = NULL
		)
	{
		Create(bManualReset, lpName, lpTimerAttributes);
		_ASSERTE(IsValid());
	}

	CWaitableTimerT
		( BOOL bManualReset
		, LPCWSTR lpName
		, LPSECURITY_ATTRIBUTES lpTimerAttributes = NULL
		)
	{
		Create(bManualReset, lpName, lpTimerAttributes);
		_ASSERTE(IsValid());
	}

	CWaitableTimerT
		( LPCSTR lpName
		, DWORD nDesiredAccess
		, BOOL bInheritHandle = FALSE
		)
	{
		Open(lpName, nDesiredAccess, bInheritHandle);
		_ASSERTE(IsValid());
	}

	CWaitableTimerT
		( LPCWSTR lpName
		, DWORD nDesiredAccess
		, BOOL bInheritHandle = FALSE
		)
	{
		Open(lpName, nDesiredAccess, bInheritHandle);
		_ASSERTE(IsValid());
	}

	CWaitableTimerT<t_bManaged>& operator=(HANDLE h)
	{
		Base::operator=(h);
		return *this;
	}

	CWaitableTimerT<t_bManaged>& operator=(const CWaitableTimerT<true>& other)
	{
		Base::operator=(other);
		return *this;
	}

	CWaitableTimerT<t_bManaged>& operator=(const CWaitableTimerT<false>& other)
	{
		Base::operator=(other);
		return *this;
	}

	HANDLE Create
		( BOOL bManualReset
		)
	{
		_ASSERTE(!IsValid());

		m_h = ::CreateWaitableTimer(NULL, bManualReset, NULL);
		return m_h;
	}

	HANDLE Create
		( BOOL bManualReset
		, LPCSTR lpName
		, LPSECURITY_ATTRIBUTES lpTimerAttributes = NULL
		)
	{
		_ASSERTE(!IsValid());

		m_h = ::CreateWaitableTimerA(lpTimerAttributes, bManualReset, lpName);
		return m_h;
	}

	HANDLE Create
		( BOOL bManualReset
		, LPCWSTR lpName
		, LPSECURITY_ATTRIBUTES lpTimerAttributes = NULL
		)
	{
		_ASSERTE(!IsValid());

		m_h = ::CreateWaitableTimerW(lpTimerAttributes, bManualReset, lpName);
		return m_h;
	}

	HANDLE Open
		( LPCSTR lpName
		, DWORD nDesiredAccess = TIMER_ALL_ACCESS
		, BOOL bInheritHandle = FALSE
		)
	{
		_ASSERTE(!IsValid());

		m_h = ::OpenWaitableTimerA(nDesiredAccess, bInheritHandle, lpName);
		return m_h;
	}

	HANDLE Open
		( LPCWSTR lpName
		, DWORD nDesiredAccess = TIMER_ALL_ACCESS
		, BOOL bInheritHandle = FALSE
		)
	{
		_ASSERTE(!IsValid());

		m_h = ::OpenWaitableTimerW(nDesiredAccess, bInheritHandle, lpName);
		return m_h;
	}

	BOOL Cancel()
	{
		_ASSERTE(IsValid());

		return ::CancelWaitableTimer(m_h);
	}

	BOOL Set
		( LONGLONG nDueTime
		, LONG lPeriod = 0
		, PTIMERAPCROUTINE pfnCompletionRoutine = NULL
		, LPVOID lpArgToCompletionRoutine = NULL
		, BOOL fResume = FALSE
		)
	{
		_ASSERTE(IsValid());
		LARGE_INTEGER liDueTime;

		liDueTime.QuadPart = nDueTime;
		return ::SetWaitableTimer(m_h, &liDueTime, lPeriod
			, pfnCompletionRoutine, lpArgToCompletionRoutine, fResume);
	}
};

typedef CWaitableTimerT<true> CWaitableTimer;
typedef CWaitableTimerT<false> CWaitableTimerHandle;

#endif // (_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)

/////////////////////////////////////////////////////////////////////////////
// MemoryResourceNotification object

#if _WIN32_WINNT >= 0x0501

template<bool t_bManaged>
class CMemoryResourceNotificationT
	: public CHandleT<t_bManaged>
{
	typedef CHandleT<t_bManaged> Base;
public:
	CMemoryResourceNotificationT()
	{ }
	CMemoryResourceNotificationT
		( const CMemoryResourceNotificationT<true>& rMemoryResourceNotification
		)
		: Base(rMemoryResourceNotification)
	{ }
	CMemoryResourceNotificationT
		( const CMemoryResourceNotificationT<false>& rMemoryResourceNotification
		)
		: Base(rMemoryResourceNotification)
	{ }
	explicit CMemoryResourceNotificationT
		( HANDLE hMemoryResourceNotification
		)
		: Base(hMemoryResourceNotification)
	{ }

	explicit CMemoryResourceNotificationT
		( MEMORY_RESOURCE_NOTIFICATION_TYPE nType
		)
	{
		Create(nType);
		_ASSERTE(IsValid());
	}

	CMemoryResourceNotificationT<t_bManaged>& operator=(HANDLE h)
	{
		Base::operator=(h);
		return *this;
	}

	CMemoryResourceNotificationT<t_bManaged>&
		operator=(const CMemoryResourceNotificationT<true>& other)
	{
		Base::operator=(other);
		return *this;
	}

	CMemoryResourceNotificationT<t_bManaged>& 
		operator=(const CMemoryResourceNotificationT<false>& other)
	{
		Base::operator=(other);
		return *this;
	}

	HANDLE Create
		( MEMORY_RESOURCE_NOTIFICATION_TYPE nType
		)
	{
		_ASSERTE(!IsValid());

		m_h = ::CreateMemoryResourceNotification(nType);
		return m_h;
	}

	BOOL Query
		( PBOOL pbResourceState
		) const
	{
		_ASSERTE(pbResourceState);
		_ASSERTE(IsValid());

		return ::QueryMemoryResourceNotification(m_h, pbResourceState);
	}

	int Query() const
	{
		_ASSERTE(IsValid());
		BOOL bResourceState;

		if (::QueryMemoryResourceNotification(m_h, &bResourceState))
			return !!bResourceState;

		return -1;
	}
};

typedef CMemoryResourceNotificationT<true> CMemoryResourceNotification;
typedef CMemoryResourceNotificationT<false> CMemoryResourceNotificationHandle;

#endif // _WIN32_WINNT >= 0x0501

/////////////////////////////////////////////////////////////////////////////

}	// namespace HTL

/////////////////////////////////////////////////////////////////////////////

#endif	// #ifndef __HTLSYNC_H__

/////////////////////////////////////////////////////////////////////////////
// End Of File htlsync.h
